﻿using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RemotingApp
{
    //public class QuartzTest
    //{
    //    public void test()
    //    {
    //        string jobnName = "jobnName";
    //        //string cronExpress = "0 0/1 * * * ?";// 每分钟执行一次
    //        string cronExpress = "0/5 * * * * ?";// 每5秒执行一次
    //        Dictionary<string, object> dictionary = new Dictionary<string,object>();
    //        dictionary.Add("cc",0);
    //        QuartzManager.addJob<MyJob>(jobnName, cronExpress, dictionary);
    //        QuartzManager.startJobs();
    //    }
    //}

    /*
    Cron表达式（在Quartz.net里面会用到）


    由7段构成：秒 分 时 日 月 星期 年（可选）
    "-" ：表示范围 ，eg: MON-WED表示星期一到星期三
    "," ：表示列举 ，eg: MON,WEB表示星期一和星期三
    "*" ：表是“每”，每月，每天，每周，每年等

    对于星期里面，SUN=1  SAT=6
    "/" :表示增量：0/15（处于分钟段里面） 每15分钟，在0分以后开始，3/20 每20分钟，从3分钟以后开始
    "?" :只能出现在日，星期段里面，表示不指定具体的值
    "L" :只能出现在日，星期段里面，是Last的缩写，一个月的最后一天，一个星期的最后一天（星期六）
    "W" :表示工作日，距离给定值最近的工作日
    "#" :表示一个月的第几个星期几，例如："6#3"表示每个月的第三个星期五（1=SUN...6=FRI,7=SAT）

    示例：
    "0 0/5 * * * ?" :每5分钟触发一次，从0秒以后开始
    "10 0/5 * * * ?" :每5分钟触发一次，从10秒以后开始。（10:00:10am, 10:05:10am)
    "0 30 10-13 ? * WED,FRI" :表示10:30,11:30,12:30,13:30，每一个星期三和星期五执行
    "0 0/30 8-9 5,20 * ?" :表示每个月5号和20号 8:00, 8:30, 9:00, 9:30执行 
    */

    public class RequestTaskInfo
    {
        public string JobName { get; set; }
        public string CronExpress { get; set; }
        public string Url { get; set; }
        public string Parms { get; set; }
        public string Description { get; set; }
        public bool Enabled { get; set; }
    }

    public class QuartzManager
    {
        #region 变量
        private static ISchedulerFactory schedulerFactory = new StdSchedulerFactory();  //scheduler工厂
        private static String JOB_GROUP_NAME = "JOBGROUP_NAME"; //Job群组名
        private static String TRIGGER_GROUP_NAME = "TRIGGERGROUP_NAME"; //触发器群组名
        #endregion

        #region 添加，删除，修改Job方法
        /// <summary>
        /// 添加一个定时任务，使用默认的任务组名，触发器名，触发器组名 
        /// </summary>
        /// <param name="pStrJobName">任务名</param>
        /// <param name="pStrCronExpress">触发器表达式</param>
        public static void addJob<T>(string pStrJobName, string pStrCronExpress, IDictionary<string, object> pDictionary, string description = null)
            where T : class,IJob
        {
            try
            {
                if (string.IsNullOrEmpty(description))
                {
                    description = pStrJobName + " >> " + pStrCronExpress;
                }
                IScheduler sched = schedulerFactory.GetScheduler();
                // 创建任务
                IJobDetail job = JobBuilder.Create<T>()
                    .WithIdentity(pStrJobName, JOB_GROUP_NAME)
                    .WithDescription(description)
                    .Build();

                // 创建触发器
                ITrigger trigger = TriggerBuilder.Create()
                    .WithIdentity(pStrJobName, TRIGGER_GROUP_NAME)
                    .WithCronSchedule(pStrCronExpress)
                    .Build();

                //给任务传参数
                foreach (KeyValuePair<string, object> kvp in pDictionary)
                {
                    job.JobDataMap.Put(kvp.Key, kvp.Value);
                }

                sched.ScheduleJob(job, trigger);
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }

        /// <summary>
        /// 移除一个任务(使用默认的任务组名，触发器名，触发器组名) 
        /// </summary>
        /// <param name="pStrJobName">任务名称</param>
        public static void RemoveJob(string pStrJobName)
        {
            try
            {
                IScheduler sched = schedulerFactory.GetScheduler();
                JobKey jobKey = new JobKey(pStrJobName);
                TriggerKey triggerKey = new TriggerKey(pStrJobName, TRIGGER_GROUP_NAME);
                sched.PauseTrigger(triggerKey);// 停止触发器  
                sched.UnscheduleJob(triggerKey);// 移除触发器  
                sched.DeleteJob(jobKey);// 删除任务  
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }

        /// <summary>
        /// 修改一个任务的触发时间(使用默认的任务组名，触发器名，触发器组名) 
        /// </summary>
        /// <param name="pStrJobName">任务名</param>
        /// <param name="pStrCronExpress">触发器表达式</param>
        public static void ModifyJobTime<T>(string pStrJobName, string pStrCronExpress, IDictionary<string, object> pDictionary) where T : class,IJob
        {
            try
            {
                IScheduler sched = schedulerFactory.GetScheduler();
                TriggerKey triggerKey = new TriggerKey(pStrJobName, TRIGGER_GROUP_NAME);
                ICronTrigger trigger = (ICronTrigger)sched.GetTrigger(triggerKey);
                if (trigger == null)
                {
                    return;
                }
                RemoveJob(pStrJobName);
                addJob<T>(pStrJobName, pStrCronExpress, pDictionary);
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }
        #endregion

        #region 启动，关闭Job
        /// <summary>
        /// 启动所有定时任务 
        /// </summary>
        public static void startJobs()
        {
            try
            {
                IScheduler sched = schedulerFactory.GetScheduler();
                sched.Start();
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }

        /// <summary>
        /// 关闭所有定时任务
        /// </summary>
        public static void ShutdownJobs()
        {
            try
            {
                IScheduler sched = schedulerFactory.GetScheduler();
                if (!sched.IsShutdown)
                {
                    sched.Shutdown(false);
                }
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }
        #endregion

    }
}
